home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / recio202.zip / design.txt < prev    next >
Text File  |  1994-05-05  |  9KB  |  193 lines

  1.     Title: RECIO DESIGN AND DEVELOPMENT NOTES
  2. Copyright: (C) 1994 William Pierpoint
  3.   Version: 2.02
  4.      Date: May 5, 1994
  5.  
  6.  
  7.  
  8. 1.0 DATA STRUCTURES
  9.  
  10. 1.1 REC structure for each record stream
  11.  
  12.     * defined in recio.h.
  13.     * one static REC for recin (included in ROPEN_MAX count).
  14.     * allocate dynamic array of RECs dimensioned to ROPEN_MAX-NREC in ropen().
  15.     * Each REC has two associated buffers:
  16.       1) record string buffer containing current record;
  17.          allocate when first record read;
  18.          reallocate if record becomes larger.
  19.       2) field string buffer containing current field;
  20.          allocate when first field read;
  21.          reallocate if field becomes larger.
  22.     * deallocate dynamic RECs and associated buffers in rclose() and
  23.       rcloseall() if all record streams closed; deallocate associated
  24.       buffers for recin with an exit function registered with atexit().
  25.  
  26.  
  27. 1.2 REC r_flags assignments
  28.  
  29.     Bit        Description
  30.    -----    -------------------------------------------------------------
  31.      0        If clear, colno start at 0; if set, colno start at 1
  32.      1      if clear, read mode; if set, write/append mode
  33.     2-6     Reserved
  34.      7        If clear, EOF not reached; if set, EOF reached
  35.     8-11    If clear, no error; else, rerror number
  36.    12-15    if clear, no warning; else, rwarning number
  37.  
  38.  
  39. 1.3 Accessing REC Members and Associated Buffers
  40.  
  41.     How do I
  42.     * access the name of the record stream?           rnames()
  43.     * access the current context number?              rcxtno()
  44.     * access the current record number?               rrecno()
  45.     * access the current field number?                rfldno()
  46.     * access the current column number?               rcolno()
  47.     * access the record string buffer?                rrecs()
  48.     * access the field string buffer?                 rflds()
  49.     * determine if column numbers start at 0 or 1     rbegcolno()
  50.     * determine if there are more records left?       reof()
  51.     * determine if there is an error on the stream?   rerror()
  52.     * determine if there is a warning on the stream?  rwarning()
  53.     * access the error message for the stream?        rerrstr()
  54.     * force an error on a record stream?              rseterr()
  55.     * clear an error on a record stream?              rclearerr()
  56.     * increase the size of the record string buffer?  rsetrecsiz()
  57.     * increase the size of the field string buffer?   rsetfldsiz()
  58.     * replace the data in the field string buffer?    rsetfldstr()
  59.     * set the field delimiter character?              rsetfldch()
  60.     * set the text delimiter character?               rsettxtch()
  61.     * set the context number?                         rsetcxtno()
  62.     * set column numbering to start at 0 or 1?        rsetbegcolno()
  63.  
  64.  
  65.  
  66. 2.0 CODE STRUCTURES
  67.  
  68. 2.1 Structure Chart
  69.  
  70.                                  ╔═════════╗
  71.                                  ║ recio.c ║
  72.                                  ╚═╤══╤══╤═╝
  73.                                    │  │  │
  74.               ╔════════╗     input │  │  │ output   ╔════════╗
  75.               ║ rget.c ╟───────────┘  │  └──────────╢ rput.c ║
  76.        char   ╚═╤════╤═╝ column       │      char   ╚═╤════╤═╝ column
  77.      delimited  │    │  delimited     │    delimited  │    │  delimited
  78.     ╔═════════╗ │    │ ╔══════════╗   │   ╔═════════╗ │    │ ╔══════════╗
  79.     ║ rgets.c ╟─┤    ├─╢ rcgets.c ║   │   ║ rputs.c ╟─┤    ├─╢ rcputs.c ║
  80.     ╚═════════╝ │    │ ╚══════════╝   │   ╚═════════╝ │    │ ╚══════════╝
  81.                 │    │                │               │    │
  82.     ╔═════════╗ │    │ ╔══════════╗   │   ╔═════════╗ │    │ ╔══════════╗
  83.     ║ rgetf.c ╟─┤    ├─╢ rcgetf.c ║   │   ║ rputf.c ╟─┤    ├─╢ rcputf.c ║
  84.     ╚═════════╝ │    │ ╚══════════╝   │   ╚═════════╝ │    │ ╚══════════╝
  85.                 │    │                │               │    │
  86.     ╔═════════╗ │    │ ╔══════════╗   │   ╔═════════╗ │    │ ╔══════════╗
  87.     ║ rbget.c ╟─┘    └─╢ rcbget.c ║   │   ║ rbput.c ╟─┘    └─╢ rcbput.c ║
  88.     ╚═════════╝        ╚══════════╝   │   ╚═════════╝        ╚══════════╝
  89.                                       │
  90.                        ╔══════════╗   │   ╔═════════╗        ╔══════════╗
  91.                        ║ rwarn.c  ╟───┴───╢ rerr.c  ╟────────╢  rfix.c  ║
  92.                        ╚══════════╝       ╚═════════╝        ╚══════════╝
  93.  
  94.  
  95. 2.2 Callback Error Function Skeleton
  96.  
  97.     if valid record pointer [risvalid(rp)]
  98.         if past end of file [reof(rp)]  (if reof test removed, past EOF will
  99.         else [error number set]           become R_EMISDAT or R_WEMPSTR)
  100.             switch error number [rerror(rp)]
  101.             case read data errors [R_ERANGE || R_EINVDAT || R_EMISDAT]
  102.             case write data errors [R_ENOPUT]
  103.                 switch context number [rcxtno(rp)]
  104.                 case RECIN
  105.                     switch field number [rfldno(rp)]
  106.                     case 1 (first field read)
  107.                     case 2 (second field read)
  108.                     ...
  109.                     endcase
  110.                 ...
  111.                 default [missing or unknown context number]
  112.                 endcase
  113.             case out of memory [R_ENOMEM]
  114.             case fatal errors [R_EINVAL || R_EINVMOD]
  115.             default [possibly set by application with rseterr()]
  116.             endcase
  117.         endif
  118.     else [invalid record pointer]
  119.         switch error number [errno]
  120.         case out of memory [ENOMEM]
  121.         case out of record or file pointers [EMFILE]
  122.         case permission denied [EACCES]
  123.         case fatal errors [EINVAL]
  124.         default [possibly set by application with rseterr()]
  125.         endcase
  126.     endif
  127.  
  128.  
  129. 2.3 Callback Warning Function Skeleton
  130.  
  131.     if valid record pointer [risvalid(rp)]
  132.         switch warning number [rwarning(rp)]
  133.         case read data warnings [R_WEMPSTR]
  134.         case write data warnings [R_WWIDTH]
  135.         case code runtime warnings [R_WNOREG]
  136.         default [possibly set by application with rsetwarn()]
  137.         endcase
  138.     endif
  139.  
  140.  
  141.  
  142. 3.0 DEVELOPMENT NOTES
  143.  
  144. 3.1 fgets (Microsoft C 5.1)
  145.  
  146. Previous notes of mine indicate that Microsoft's fgets function does not
  147. work correctly when it reads a line of text that consists of only a newline.
  148. However this can be worked around by first setting the string buffer to an
  149. empty string.  If you plan on retaining the newline, you will need to test
  150. this further.  The fgets function is used twice in the rgetrec function.
  151. If porting to Microsoft C, you may need to implement this fix in rget.c:
  152.  
  153.      *rrecs(rp) = '\0';  /* just prior to the first fgets (added v1.20) */
  154.      *str = '\0';        /* just prior to the second fgets */
  155.  
  156.  
  157. 3.2 fopen (Borland C 3.1)
  158.  
  159. fopen() calls __openfp() calls open().  Borland's "Library Reference"
  160. documents error numbers for open(), but not for fopen().  These error
  161. numbers are ENOENT, EMFILE, EACCES, and EINVACC.  Because ropen() screens
  162. the access code, the EINVACC error should not occur from the recio library.
  163.  
  164.  
  165. 3.3 strtol & strtoul (Borland C 3.1)
  166.  
  167. These functions stop consuming input once they overflow, setting ERANGE.
  168. Hence endptr can point into the middle of a sequence of valid characters
  169. having the expected form as given in ANSI X3.159-1989, Sections 4.10.1.5
  170. and 4.10.1.6.  IMHO this characteristic is not in conformance with the
  171. ANSI standard as endptr should only point to the first unrecognized
  172. character or to the terminating null character.  Borland's strtod does
  173. not have this problem.
  174.  
  175. Note that ANSI X3.159-1989 Section 4.10.1.6 allows strtoul (unsigned
  176. long) to have an optional negative sign.  A negative unsigned long?
  177. Borland 3.1 strtoul converts a negative long to an unsigned number
  178. without error.  But I prefer to trap any negative numbers input to
  179. unsigned fields.  So str2ul is a wrapper function for strtoul that
  180. first tests for a negative number and if one is found, flags the data
  181. as invalid and returns zero.
  182.  
  183. The test suite includes -0 as a data value.  The strtol function traps
  184. this as an ERANGE error and returns the overflow limit.  The rfixi and
  185. rfixl functions substitute zero.
  186.  
  187. 3